export default class utils {
  /**
   * 返回一个格式化日期
   * @param date Date类型
   * @param formatter date || datetime || yyyy年MM月dd日 HH:mm:ss(指定日期格式) || 自定义函数
   * @param isPad 是否补零
   */
  static formatDate(date, formatter, isPad = false) {
    if (!(date instanceof Date)) {
      throw new TypeError('argument date must be a Date')
    }

    //参数归一化
    const formatHelper = function (formatter) {
      if (typeof formatter === 'function') {
        return formatter
      }
      if (typeof formatter !== 'string') {
        throw new TypeError('formatter must be a string')
      }
      if (formatter === 'date') {
        formatter = 'yyyy-MM-dd'
      }
      if (formatter === 'datetime') {
        formatter = 'yyyy-MM-dd HH:mm:ss'
      }
      const formatFunc = (dateInfo) => {
        const { yyyy, MM, dd, HH, mm, ss, ms } = dateInfo
        return formatter
          .replaceAll('yyyy', yyyy)
          .replaceAll('MM', MM)
          .replaceAll('dd', dd)
          .replaceAll('HH', HH)
          .replaceAll('mm', mm)
          .replaceAll('ss', ss)
          .replaceAll('ms', ms)
      }
      return formatFunc
    }
    formatter = formatHelper(formatter)
    const dateInfo = {
      yyyy: date.getFullYear().toString(),
      MM: (date.getMonth() + 1).toString(),
      dd: date.getDate().toString(),
      HH: date.getHours().toString(),
      mm: date.getMinutes().toString(),
      ss: date.getSeconds().toString(),
      ms: date.getMilliseconds().toString(),
    }

    // 补零
    function _pad(prop, len) {
      dateInfo[prop] = dateInfo[prop].padStart(len, '0')
    }

    if (isPad) {
      _pad('yyyy', 4)
      _pad('MM', 2)
      _pad('dd', 2)
      _pad('HH', 2)
      _pad('mm', 2)
      _pad('ss', 2)
      _pad('ms', 3)
    }
    const result = formatter(dateInfo)
    return result
  }

  // /**
  //  * 将数字转换成中文
  //  * @param number 数字 支持小数（默认取三位）
  //  * @param isTraditional 是否显示大写繁体数字 默认为false
  //  * @returns {*}
  //  */
  // static toChineseNumber(number, isTraditional = false) {
  //   if (!number) {
  //     return "零";
  //   }

  //   const chineseMap = [
  //     "零",
  //     "一",
  //     "二",
  //     "三",
  //     "四",
  //     "五",
  //     "六",
  //     "七",
  //     "八",
  //     "九",
  //   ];
  //   const units = ["", "十", "百", "千"];
  //   const bigUnits = ["", "万", "亿"];

  //   /**
  //    * 去掉连续的零和末尾的零
  //    * @param str
  //    * @returns {*}
  //    */
  //   function handleZero(str) {
  //     return str.replace(/零+/g, "零").replace(/零$/, "");
  //   }

  //   function transformNumber(strNumber) {
  //     let str = "";
  //     for (let i = 0; i < strNumber.length; i++) {
  //       let c = chineseMap[strNumber[i]];
  //       let u = units[strNumber.length - 1 - i];
  //       if (c === "零") {
  //         u = "";
  //       }
  //       str += c + u;
  //     }
  //     return handleZero(str);
  //   }

  //   let decimalStr = "";
  //   //是小数
  //   if (number.toString().indexOf(".") !== -1) {
  //     number = parseFloat(number);
  //     const splitNumber = number.toString().split(".");
  //     //整数部分
  //     number = splitNumber[0];
  //     //小数部分（默认取三位）
  //     decimalStr = transformNumber(splitNumber[1].slice(0, 3));
  //   } else {
  //     number = parseInt(number);
  //   }

  //   //?=正向前查找 和 $ 确保前瞻匹配会从字符串的末尾开始匹配
  //   const splitNumber = number
  //     .toString()
  //     .replace(/(?=(\d{4})+$)/g, ",")
  //     .split(",")
  //     .filter(Boolean);
  //   let result = "";
  //   for (let j = 0; j < splitNumber.length; j++) {
  //     let c = transformNumber(splitNumber[j]);
  //     let u = bigUnits[splitNumber.length - j - 1];
  //     //中间四位是零，显示成中文零，不带单位
  //     if (c === "") {
  //       c = "零";
  //       u = "";
  //     }
  //     result += c + u;
  //   }
  //   result = handleZero(result);

  //   if (decimalStr) {
  //     result += `点${decimalStr}`;
  //   }

  //   if (isTraditional) {
  //     const numberMap = {
  //       零: "零",
  //       一: "壹",
  //       二: "贰",
  //       三: "叁",
  //       四: "肆",
  //       五: "伍",
  //       六: "陆",
  //       七: "柒",
  //       八: "捌",
  //       九: "玖",
  //       十: "拾",
  //       百: "佰",
  //       千: "仟",
  //       // '万': '万',
  //       // '亿': '亿',
  //       // '点': '点'
  //     };
  //     result = result
  //       .split("")
  //       .map((str) => (numberMap[str] ? numberMap[str] : str))
  //       .join("");
  //   }
  //   return result;
  // }

  // /**
  //  * 分时执行函数封装
  //  * @param {*} tasks 待执行任务数组
  //  * @param {*} scheduler 调度器（可选）
  //  * scheduler由调用者传入，不传使用内部默认调度器
  //  * scheduler执行时，将当前任务作为参数丢给外部，由外部决定合适执行该任务，
  //  * isGoOn:执行chunkTask的时候，外部还需传入一个isGOOn函数，内部根据函数返回值，判断是否往后执行后续任务
  //  * @returns
  //  */
  // static performanceTask(tasks, scheduler) {
  //   if (!Array.isArray(tasks) || tasks.length === 0) return;

  //   if (!scheduler || typeof scheduler !== "function") {
  //     if (typeof requestIdleCallback === "function") {
  //       scheduler = (chunkTask) => {
  //         requestIdleCallback((deadLine) => {
  //           chunkTask(() => deadLine.timeRemaining() > 0);
  //         });
  //       };
  //     } else {
  //       scheduler = (chunkTask) => {
  //         setTimeout(() => {
  //           chunkTask(() => true);
  //         }, 0);
  //       };
  //     }
  //   }
  //   let executeIndex = 0;
  //   //捕获到错误，不往后执行
  //   let catchError = false;

  //   function _run() {
  //     scheduler((isGoOn) => {
  //       while (executeIndex < tasks.length && isGoOn() && !catchError) {
  //         try {
  //           tasks[executeIndex++]();
  //         } catch (error) {
  //           catchError = true;
  //           console.error(`task_${executeIndex} execute failed`, error);
  //         }
  //       }
  //       if (!catchError && executeIndex < tasks.length) {
  //         _run();
  //       }
  //     });
  //   }

  //   _run();
  // }

  // /**
  //  * 全屏切换
  //  */
  // static fullscreenSwitch(cb) {
  //   let elem = document.documentElement;
  //   if (
  //     document.fullscreenElement ||
  //     document.mozFullScreenElement ||
  //     document.webkitFullscreenElement ||
  //     document.msFullscreenElement
  //   ) {
  //     if (document.exitFullscreen) {
  //       document.exitFullscreen();
  //     } else if (document.mozCancelFullScreen) {
  //       // Firefox
  //       document.mozCancelFullScreen();
  //     } else if (document.webkitExitFullscreen) {
  //       // Chrome, Safari 和 Opera
  //       document.webkitExitFullscreen();
  //     } else if (document.msExitFullscreen) {
  //       // IE/Edge
  //       document.msExitFullscreen();
  //     }
  //     if (typeof cb === "function") {
  //       cb(false);
  //     }
  //   } else {
  //     if (elem.requestFullscreen) {
  //       elem.requestFullscreen();
  //     } else if (elem.mozRequestFullScreen) {
  //       // Firefox
  //       elem.mozRequestFullScreen();
  //     } else if (elem.webkitRequestFullscreen) {
  //       // Chrome, Safari 和 Opera
  //       elem.webkitRequestFullscreen();
  //     } else if (elem.msRequestFullscreen) {
  //       // IE/Edge
  //       elem.msRequestFullscreen();
  //     }
  //     if (typeof cb === "function") {
  //       cb(true);
  //     }
  //   }
  // }

  // // 复制文字
  // static copyToClipboard(text, inputEle) {
  //   return new Promise((resolve) => {
  //     if (inputEle && inputEle.value) {
  //       inputEle.select();
  //       document.execCommand("Copy");
  //       resolve();
  //     } else if (navigator.clipboard) {
  //       navigator.clipboard
  //         .writeText(text)
  //         .then(resolve)
  //         .catch((e) => console.log(e));
  //     } else {
  //       let input = document.createElement("input");
  //       input.value = text;
  //       input.style.position = "absolute";
  //       input.style.zIndex = -1;
  //       document.body.appendChild(input);
  //       input.select();
  //       document.execCommand("Copy");
  //       input.remove();
  //       resolve();
  //     }
  //   });
  // }

  static sleepWait(delay = 1000) {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(delay)
      }, delay)
    })
  }

  /**
   * 防抖函数
   * @param {Function} fn - 需要防抖的函数
   * @param {number} delay - 延迟时间（毫秒）
   * @returns {Function} - 返回一个防抖后的函数
   */
  static debounce(fn, delay) {
    let timer = null
    return function (...args) {
      if (timer) {
        clearTimeout(timer) // 如果计时器存在，清除之前的计时器
      }
      timer = setTimeout(() => {
        fn.apply(this, args) // 延迟执行函数
        timer = null // 执行完后清空计时器
      }, delay)
    }
  }

  // /**
  //  * @param {Function} func
  //  * @param {number} wait
  //  * @param {boolean} immediate
  //  * @return {*}
  //  */
  // static debounce(func, wait, immediate) {
  //   let timeout, args, context, timestamp, result;

  //   const later = function () {
  //     // 据上一次触发时间间隔
  //     const last = +new Date() - timestamp;

  //     // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
  //     if (last < wait && last > 0) {
  //       timeout = setTimeout(later, wait - last);
  //     } else {
  //       timeout = null;
  //       // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
  //       if (!immediate) {
  //         result = func.apply(context, args);
  //         if (!timeout) context = args = null;
  //       }
  //     }
  //   };

  //   return function (...args) {
  //     context = this;
  //     timestamp = +new Date();
  //     const callNow = immediate && !timeout;
  //     // 如果延时不存在，重新设定延时
  //     if (!timeout) timeout = setTimeout(later, wait);
  //     if (callNow) {
  //       result = func.apply(context, args);
  //       context = args = null;
  //     }

  //     return result;
  //   };
  // }

  /**
   * This is just a simple version of deep copy
   * Has a lot of edge cases bug
   * If you want to use a perfect deep copy, use lodash's _.cloneDeep
   * @param {Object} source
   * @returns {Object}
   */
  static deepClone(source) {
    if (!source && typeof source !== 'object') {
      throw new Error('error arguments', 'deepClone')
    }
    const targetObj = source.constructor === Array ? [] : {}
    Object.keys(source).forEach((keys) => {
      if (source[keys] && typeof source[keys] === 'object') {
        targetObj[keys] = this.deepClone(source[keys])
      } else {
        targetObj[keys] = source[keys]
      }
    })
    return targetObj
  }

  /**
   * 高亮匹配文本的通用函数
   * @param {string} originText - 原始文本
   * @param {string} matchText - 需要高亮的匹配文本
   * @returns {string} 包含高亮span标签的HTML字符串
   */
  static highlightText(originText, matchText) {
    // 安全校验
    if (!matchText || typeof originText !== 'string') return originText

    // 转义正则特殊字符
    const escapedMatch = matchText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')

    // 创建全局正则表达式（不区分大小写可以加 i 标志）
    const regex = new RegExp(`(${escapedMatch})`, 'gi')

    // 替换匹配项
    return originText.replace(regex, '<span class="highlight-text">$1</span>')
  }

  //生成唯一主键id
  static getUUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      const r = (Math.random() * 16) | 0
      const v = c === 'x' ? r : (r & 0x3) | 0x8
      return v.toString(16)
    })
  }

  // xeutils.toTreeArray优化- 自动添加parentKey
  // 将一个树结构转成数组列表
  static toTreeArray(array, options) {
    const fn = (result, array, parentId, opts) => {
      let optChildren = opts.children
      let optData = opts.data
      let optClear = opts.clear
      let optKey = opts.key
      let optParentKey = opts.parentKey
      array.forEach((item) => {
        let children = item[optChildren]
        if (optData) {
          item = item[optData]
        }
        result.push({
          [optParentKey]: parentId,
          ...item,
        })
        if (children && children.length) {
          fn(result, children, item[optKey], opts)
        }
        if (optClear) {
          delete item[optChildren]
        }
      })
      return result
    }
    return fn([], array, null, {
      parentKey: 'parentId',
      key: 'id',
      children: 'children',
      ...options,
    })
  }

  // 将一个数组列表转成树结构
  static arrayToTree(items, options = {}) {
    if (!Array.isArray(items)) {
      return []
    }
    const {
      idKey = 'id', // id字段名
      parentKey = 'parentId', // parent字段名
      childrenKey = 'children', // children字段名
    } = options

    const result = []
    const itemMap = {}

    // 建立映射
    for (const item of items) {
      itemMap[item[idKey]] = { ...item, [childrenKey]: [] }
    }

    // 构建树
    for (const item of items) {
      const id = item[idKey]
      const parentId = item[parentKey]
      const treeItem = itemMap[id]

      if (!parentId || parentId === '' || !itemMap[parentId]) {
        // 没有父节点或父节点不存在，作为根节点
        result.push(treeItem)
      } else {
        // 添加到父节点的children中
        itemMap[parentId][childrenKey].push(treeItem)
      }
    }

    return result
  }
}
